Numpy¶
NumPy, which stands for Numerical Python, is a fundamental package for scientific computing in Python. It provides support for large, multi-dimensional arrays and matrices, along with a collection of mathematical functions to operate on these arrays. The impact of NumPy on STEM (Science, Technology, Engineering, and Mathematics) computing has been profound and can be summarized in several key points:
- Efficient Array Operations: NumPy provides a powerful array object,
numpy.ndarray
, which is highly efficient for numerical operations. This allows for the manipulation of large datasets and the execution of complex mathematical operations on arrays with relative ease. - Vectorization: NumPy encourages vectorized operations, where mathematical operations are performed on entire arrays rather than on individual elements. This leads to more concise and readable code and often results in improved performance.
- Interoperability: NumPy seamlessly integrates with other scientific computing libraries and tools, making it a fundamental building block for a wide range of applications. Many other libraries, such as SciPy, scikit-learn, and Pandas, are built on top of NumPy.
- Mathematical Functions: NumPy provides a comprehensive set of mathematical functions for performing operations such as linear algebra, Fourier analysis, random number generation, and more. These functions are highly optimized and contribute to the overall efficiency of numerical computations.
- Memory Efficiency: NumPy's array representation and memory management make it efficient in terms of memory usage. It allows for the manipulation of large datasets without the need for extensive memory overhead.
- Broadcasting: NumPy supports broadcasting, a powerful feature that allows operations between arrays of different shapes and sizes. This enables efficient computation on arrays without the need for explicit looping constructs.
- Community and Ecosystem: The NumPy community is vibrant and actively contributes to its development. The ecosystem around NumPy includes a plethora of libraries and tools that leverage its capabilities, creating a rich environment for scientific computing.
- Teaching and Research: NumPy has become a standard tool in educational settings and research environments. Its simplicity, combined with its powerful capabilities, makes it an excellent choice for teaching and conducting scientific experiments.
In summary, NumPy has had a significant impact on STEM computing by providing a robust foundation for numerical operations in Python. Its efficiency, ease of use, and integration with other libraries make it an essential tool for scientists, engineers, and researchers across various disciplines.
In order to use Numpy module, we need to import it first. A conventional way to import it is to use “np” as a shortened name.
import numpy as np
WARNING! Of course, you could call it any name, but conventionally, “np” is accepted by the whole community and it is a good practice to use it for obvious purposes.
NumPy Array¶
A NumPy array is a fundamental data structure in the NumPy library that represents a grid of values, all of the same type. It is an N-dimensional container that provides a convenient way to store and manipulate large datasets.
# Creating a 1D NumPy array
arr_1d = np.array([1, 2, 3, 4, 5])
# Displaying the array and its properties
print("1D Array:")
print(arr_1d)
print("Shape:", arr_1d.shape) # Shape of the array
print("Data Type:", arr_1d.dtype) # Data type of the array elements
print("Size:", arr_1d.size) # Number of elements in the array
print("Dimension:", arr_1d.ndim) # Number of dimensions
# Creating a 2D NumPy array
arr_2d = np.array([[1, 2, 3], [4, 5, 6]])
# Displaying the 2D array and its properties
print("\n2D Array:")
print(arr_2d)
print("Shape:", arr_2d.shape)
print("Data Type:", arr_2d.dtype)
print("Size:", arr_2d.size)
print("Dimension:", arr_2d.ndim)
# Array operations
sum_arr = arr_1d + arr_1d # Element-wise addition
prod_arr = arr_1d * 2 # Scalar multiplication
dot_product = np.dot(arr_1d, arr_1d) # Dot product
# Displaying results of array operations
print("\nArray Operations:")
print("Sum of Arrays:", sum_arr)
print("Scalar Multiplication:", prod_arr)
print("Dot Product:", dot_product)
1D Array: [1 2 3 4 5] Shape: (5,) Data Type: int32 Size: 5 Dimension: 1 2D Array: [[1 2 3] [4 5 6]] Shape: (2, 3) Data Type: int32 Size: 6 Dimension: 2 Array Operations: Sum of Arrays: [ 2 4 6 8 10] Scalar Multiplication: [ 2 4 6 8 10] Dot Product: 55
Matplotlib¶
Visualizing data is usually the best way to convey important engineering and science ideas and information, especially if the information is made up of many, many numbers. The ability to visualize and plot data quickly and in many different ways is one of Python’s most powerful features.
Python has numerous graphics functions that enable you to efficiently display plots, surfaces, volumes, vector fields, histograms, animations, and many other data plots. In Python, the matplotlib is the most important package that to make a plot, you can have a look of the matplotlib gallery and get a sense of what could be done there. Usually the first thing we need to do to make a plot is to import the matplotlib package. In Jupyter notebook, we could show the figure directly within the notebook and also have the interactive operations like pan, zoom in/out, and so on using the magic command -
%matplotlib widget
import numpy as np
import matplotlib.pyplot as plt
2D Plotting¶
The basic plotting function is plot(x,y). The plot function takes in two lists/arrays, x and y, and produces a visual display of the respective points in x and y.
TRY IT! Given the lists x = [0, 1, 2, 3] and y = [0, 1, 4, 9], use the plot function to produce a plot of x versus y.
fig1=plt.figure()
x = [0, 1, 2, 3]
y = [0, 1, 4, 9]
plt.plot(x, y)
[<matplotlib.lines.Line2D at 0x1c356dd2090>]
You will notice in the above figure that by default, the plot function connects each point with a blue line. To make the function look smooth, use a finer discretization points. Note that, before you plot the next figure, you need to turn off the interactive plot by pressing the stop interaction button on the top right of the figure. Otherwise, the next figure will be plotted in the same frame. Or we could simply using the magic function %matplotlib inline to turn off the interactive features.
fig2 = plt.figure()
X = np.linspace(-5,5, 100)
plt.plot(X, X**2, label='fine')
plt.plot(x, y, label='coarse')
plt.legend()
plt.show()
To change the marker or line, you can put a third input argument into plot, which is a string that specifies the color and line style to be used in the plot. For example, plot(x,y,'ro') will plot the elements of x against the elements of y using red, r, circles, 'o'. The possible specifications are shown below in the table.
Symbol | Description | Symbol | Description |
---|---|---|---|
b | blue | T | T |
g | green | s | square |
r | red | d | diamond |
c | cyan | v | triangle (down) |
m | magenta | ^ | triangle (up) |
y | yellow | < | triangle (left) |
k | black | > | triangle (right) |
w | white | p | pentagram |
. | point | h | hexagram |
o | circle | - | solid |
x | x-mark | : | dotted |
+ | plus | -. | dashdot |
* | star | -- | dashed |
We can create a table of plots on a single figure using the subplot function. The subplot function takes three inputs: the number of rows of plots, the number of columns of plots, and to which plot all calls to plotting functions should plot. You can move to a different subplot by calling the subplot again with a different entry for the plot location.
There are several other plotting functions that plot x versus y data. Some of them are scatter, bar, loglog, semilogx, and semilogy. scatter works exactly the same as plot except it defaults to red circles (i.e., plot(x,y,'ro') is equivalent to scatter(x,y)). The bar function plots bars centered at x with height y. The loglog, semilogx, and semilogy functions plot the data in x and y with the x and y axis on a log scale, the x axis on a log scale and the y axis on a linear scale, and the y axis on a log scale and the x axis on a linear scale, respectively.
x = np.arange(11)
y = x**2
fig3=plt.figure()
plt.subplot(2, 3, 1)
plt.plot(x,y)
plt.title('Plot')
plt.xlabel('X')
plt.ylabel('Y')
plt.grid()
plt.subplot(2, 3, 2)
plt.scatter(x,y)
plt.title('Scatter')
plt.xlabel('X')
plt.ylabel('Y')
plt.grid()
plt.subplot(2, 3, 3)
plt.bar(x,y)
plt.title('Bar')
plt.xlabel('X')
plt.ylabel('Y')
plt.grid()
plt.subplot(2, 3, 4)
plt.loglog(x,y)
plt.title('Loglog')
plt.xlabel('X')
plt.ylabel('Y')
plt.grid(which='both')
plt.subplot(2, 3, 5)
plt.semilogx(x,y)
plt.title('Semilogx')
plt.xlabel('X')
plt.ylabel('Y')
plt.grid(which='both')
plt.subplot(2, 3, 6)
plt.semilogy(x,y)
plt.title('Semilogy')
plt.xlabel('X')
plt.ylabel('Y')
plt.grid()
plt.tight_layout()
plt.show()
LMFIT¶
lmfit
is a Python library designed for nonlinear optimization and curve fitting, built on top of SciPy
. It provides a flexible and high-level interface for fitting mathematical models to experimental data. Key features include:
Parameterization:
- Users can define models with parameters, initial values, constraints, and relationships.
- Parameters can be fixed, have bounds, or vary freely during optimization.
Modeling:
- Supports predefined and user-defined models.
- Allows combining multiple simple models to create complex ones.
Optimization Algorithms:
- Provides various optimization algorithms (e.g., Levenberg-Marquardt, Nelder-Mead) for fitting models to data.
Uncertainty Estimation:
- Tools for estimating uncertainties in fitted parameters, including confidence intervals and standard errors.
- Monte Carlo methods for uncertainty propagation.
Interactive Fitting:
- Interactive tools for exploring and refining fits, aiding visualization and understanding.
Integration with Plotting Libraries:
- Integrates well with popular plotting libraries such as
Matplotlib
. - Functions for plotting data, models, and residuals.
- Integrates well with popular plotting libraries such as
Customization:
- Users have control over fitting procedures, convergence criteria, and optimization aspects.
from lmfit import Model
# Define a simple model function
def model(x, amplitude, frequency, phase):
return amplitude * np.sin(2 * np.pi * frequency * x + phase)
# Generate synthetic data
x_data = np.linspace(0, 2 * np.pi, 100)
y_data = model(x_data, amplitude=1.0, frequency=1.0, phase=0.0) + 0.1 * np.random.normal(size=len(x_data))
# Create an lmfit Model
sin_model = Model(model)
# Set initial parameter values
params = sin_model.make_params(amplitude=1.0, frequency=1.0, phase=0.0)
# Fit the model to the data
result = sin_model.fit(y_data, params, x=x_data)
# Print fit results
print(result.fit_report())
# Plot the data and the fitted model
plt.close("all")
plt.scatter(x_data, y_data, label='Data')
plt.plot(x_data, result.best_fit, label='Fit', color='red')
plt.legend()
plt.show()
[[Model]] Model(model) [[Fit Statistics]] # fitting method = leastsq # function evals = 13 # data points = 100 # variables = 3 chi-square = 1.13112857 reduced chi-square = 0.01166112 Akaike info crit = -442.195431 Bayesian info crit = -434.379921 R-squared = 0.97952704 [[Variables]] amplitude: 1.03859024 +/- 0.01524418 (1.47%) (init = 1) frequency: 1.00162429 +/- 0.00128542 (0.13%) (init = 1) phase: -0.03567245 +/- 0.02898489 (81.25%) (init = 0) [[Correlations]] (unreported correlations are < 0.100) C(frequency, phase) = -0.8611